package com.stars.easyms.datasource.holder;

import com.stars.easyms.datasource.EasyMsDataSource;
import com.stars.easyms.datasource.EasyMsMasterSlaveDataSource;
import com.stars.easyms.datasource.enums.DataSourceType;
import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>className: EasyMsMasterSlaveDataSourceHolder</p>
 * <p>description: EasyMs当前线程多数据源持有者</p>
 *
 * @author guoguifang
 * @version 1.1.0
 * @date 2019-02-28 17:02
 */
public final class EasyMsMasterSlaveDataSourceHolder {

    private static final ThreadLocal<EasyMsMasterSlaveDataSource> EASY_MS_MASTER_SLAVE_DATA_SOURCE
            = new NamedThreadLocal<>("Current EasyMsMasterSlaveDataSource");

    private static final ThreadLocal<Map<EasyMsMasterSlaveDataSource, Map<DataSourceType, EasyMsDataSource>>> FIXED_DATA_SOURCE_RESOURCES
            = new NamedThreadLocal<>("Fixed dataSource resources");

    public static void putMasterSlaveDataSource(EasyMsMasterSlaveDataSource dataSource) {
        EASY_MS_MASTER_SLAVE_DATA_SOURCE.set(dataSource);
    }

    public static EasyMsMasterSlaveDataSource getMasterSlaveDataSource() {
        return EASY_MS_MASTER_SLAVE_DATA_SOURCE.get();
    }

    public static void clearMasterSlaveDataSource() {
        EASY_MS_MASTER_SLAVE_DATA_SOURCE.remove();
    }

    public static void fixedDataSource() {
        FIXED_DATA_SOURCE_RESOURCES.set(new HashMap<>(8));
    }

    public static boolean isFixedDataSource() {
        return FIXED_DATA_SOURCE_RESOURCES.get() != null;
    }

    @Nullable
    public static EasyMsDataSource getFixedDataSource(@NonNull EasyMsMasterSlaveDataSource masterSlaveDataSource,
                                                      @NonNull DataSourceType dataSourceType) {
        Map<DataSourceType, EasyMsDataSource> fixedEasyMsDataSourceMap = getCurrentFixedDataSourceResources().get(masterSlaveDataSource);
        if (fixedEasyMsDataSourceMap != null) {
            return fixedEasyMsDataSourceMap.get(dataSourceType);
        }
        return null;
    }

    public static void bindFixedDataSource(@NonNull EasyMsMasterSlaveDataSource masterSlaveDataSource,
                                           @NonNull DataSourceType dataSourceType, @NonNull EasyMsDataSource easyMsDataSource) {
        Map<DataSourceType, EasyMsDataSource> fixedEasyMsDataSourceMap =
                getCurrentFixedDataSourceResources().computeIfAbsent(masterSlaveDataSource, e -> new HashMap<>(2));
        EasyMsDataSource existEasyMsDataSource = fixedEasyMsDataSourceMap.get(dataSourceType);
        if (existEasyMsDataSource != null && !existEasyMsDataSource.equals(easyMsDataSource)) {
            throw new IllegalStateException("Fixed dataSource resource already exist");
        } else {
            fixedEasyMsDataSourceMap.put(dataSourceType, easyMsDataSource);
        }
    }

    public static void clearFixedDataSource() {
        FIXED_DATA_SOURCE_RESOURCES.remove();
    }

    private static Map<EasyMsMasterSlaveDataSource, Map<DataSourceType, EasyMsDataSource>> getCurrentFixedDataSourceResources() {
        Map<EasyMsMasterSlaveDataSource, Map<DataSourceType, EasyMsDataSource>> fixedDataSourceResources = FIXED_DATA_SOURCE_RESOURCES.get();
        Assert.notNull(fixedDataSourceResources, "Fixed dataSource resources is not active");
        return fixedDataSourceResources;
    }

    private EasyMsMasterSlaveDataSourceHolder() {
    }
}